package com.longcheer.weibo;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.longcheer.weibo.util.ImageUtils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class ImageManager {  
    private static final String TAG = "ImageManager";
    
    private Map<String, Bitmap> mCache;
    
    private static ImageManager mInstance;
    private ExecutorService mExcutor = Executors.newFixedThreadPool(20);
    
    public static final int MIDDLE_IMAGE = 0;
    public static final int LITTLE_IMAGE = 1;
    public static final int AVATAR_IMAGE = 3;
    public static final int SOURCE_IMAGE = 4;
   
    private ImageManager() {  
        mCache = new HashMap<String, Bitmap>();  
    }
    
    public static ImageManager getInstance() {
        if (mInstance == null) {
            mInstance = new ImageManager();
        }
        return mInstance;
    }
   
    public void loadImage(final String imageUrl, final Callback callback) {  
        loadImage(imageUrl, LITTLE_IMAGE, callback);
    }
    
    public void loadImage(final String imageUrl, int imageType, final Callback callback) {  
        if (mCache.containsKey(imageUrl)) {  
            Bitmap bitmap = mCache.get(imageUrl);
            if (bitmap != null) {  
                callback.imageLoaded(bitmap, imageUrl);
                return;
            }  
        }

        final Handler handler = new Handler() {  
            @Override  
            public void handleMessage(android.os.Message message) {  
                callback.imageLoaded((Bitmap)message.obj, imageUrl);  
            }  
        };
        mExcutor.execute(new DownloadTask(handler, imageUrl, imageType));
    }
    
    public void removeBitmap(String imageUrl) {
        if (mCache.containsKey(imageUrl)) {
            Bitmap bitmap = mCache.get(imageUrl);
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
            
            mCache.remove(imageUrl);
        }
    }
   
    public interface Callback {  
        public void imageLoaded(Bitmap bitmap, String imageUrl);
        
        
    }
    
    class DownloadTask implements Runnable {
        
        private Handler mHandler;
        private String mImageUrl;
        private int mType;
        
        public DownloadTask(Handler handler, String imageUrl, int imageType) {
            mHandler = handler;
            mImageUrl = imageUrl;
            mType = imageType;
        }

        @Override
        public void run() {
            byte[] bytes = ImageUtils.getImageFromHTTP(mImageUrl);
            if (bytes != null) {
                Bitmap bitmap;
                if (mType == LITTLE_IMAGE) {
                    bitmap = ImageResizer.getLittleImage(bytes);
                } else if (mType == MIDDLE_IMAGE) {
                    bitmap = ImageResizer.getMiddleImage(bytes);
                } else if (mType == AVATAR_IMAGE) {
                    bitmap = ImageResizer.getAvatarImage(bytes);
                } else {
                    bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                }
                
                if (bitmap != null) {
                    Message msg = mHandler.obtainMessage(0, bitmap);
                    mHandler.sendMessage(msg);
                }
            }
        }
    }
    
    public static class ImageResizer {
        public static final int LITTLE_HEIGHT = 120;
        public static final int LITTLE_WIDTH = 120;
        public static final int MIDDLE_HEIGHT = 300;
        public static final int MIDDLE_WIDTH = 300;
        public static final int AVATAR_HEIGHT = 50;
        public static final int AVATAR_WIDTH = 50;
        
        public static Bitmap getAvatarImage(byte[] bytes) {
            return resizeImage(bytes, AVATAR_HEIGHT, AVATAR_WIDTH);
        }

        public static Bitmap getLittleImage(byte[] bytes) {
            return resizeImage(bytes, LITTLE_HEIGHT, LITTLE_WIDTH);
        }
        
        public static Bitmap getMiddleImage(byte[] bytes) {
            return resizeImage(bytes, MIDDLE_HEIGHT, MIDDLE_WIDTH);
        }
        
        private static Bitmap resizeImage(byte[] bytes, int dstHeight, int dstWidth) {
            BitmapFactory.Options opts = new BitmapFactory.Options(); 
            opts.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
            
            int rHeight = opts.outHeight;
            int rWidth = opts.outWidth;
            
            int hRatio = (int)Math.ceil(rHeight / dstHeight);
            int wRatio = (int)Math.ceil(rWidth / dstWidth);
            Log.d(TAG, String.format("[rHeight=%d rWidth=%d hRatio=%d wRatio=%d]", 
                    rHeight, rWidth, hRatio, wRatio));
            
            if (hRatio > 1 || wRatio > 1) {
                if (wRatio > hRatio) {
                    opts.inSampleSize = wRatio;
                } else {
                    opts.inSampleSize = hRatio;
                }
            }
            
            opts.inJustDecodeBounds = false;
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
        }
    }
}  
